﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Acoris.Foundation
{
    #if WPF
        [Serializable]
    #endif
    public sealed class Stack1<T>:IEnumerable<T>
    {
        private int _limit;
        private Deque<T> _deque;
        private object _sync;

        #region Constructor

        public Stack1() : this(100) { }
        public Stack1(int limit):this(limit,4) { }
        public Stack1(int limit,int capacity) {
            _deque = new Deque<T>(capacity);
            _limit = limit;
            _sync = new object();
        }

#endregion

        public void Push(T item)
        {
            //队尾出
            //队头进栈出栈
            if(_limit <= 0) {
                _deque.PushHead(item);
            }
            else if(_deque.Count >= _limit) {
                _deque.PopTail();
                _deque.PushHead(item);
            }            
        }

        public T Pop()
        {
            if(_deque.Count == 0) {
                throw new InvalidOperationException();
            }
            return _deque.PopHead();
        }

        public T Peek()
        {
            if(_deque.Count == 0) {
                return default(T);
            }
            var array = _deque.GetArray();
            var head = _deque.GetHead();
            return array[head + 1];
        }

        public IEnumerator<T> GetEnumerator()
        {
            var array = _deque.GetArray();
            var head = _deque.GetHead();
            for(int i = 0; i < _deque.Count; i++) {
                yield return array[head + i + 1];
            }
            yield break;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            var array = _deque.GetArray();
            var head = _deque.GetHead();
            for (int i = 0; i < _deque.Count; i++) {
                yield return array[head + i + 1];
            }
            yield break;
        }

        public int Count {
            get {
                return _deque.Count;
            }
        }

        public int Limit {
            get {
                return _limit;
            }
            set {
                _limit = value;
            }
        }

        public object Synchronize {
            get {
                return _sync;
            }
        }
    }
}
